package frontend;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.omg.CORBA.StringHolder;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.InvalidName;
import org.omg.CosNaming.NamingContextPackage.NotFound;


class DRSServiceClientImpl {
	private DRStore.DRSService target = null;
	private org.omg.CORBA.ORB orb = null;
	public String clientID;
	ClientInvocation ci;
	private final ExecutorService threadPool;
	//String name = null;

	/**
	 * Constructor for DRSServiceClientImpl
	 * 
	 * @throws IOException
	 * @throws org.omg.CORBA.ORBPackage.InvalidName 
	 * @throws InvalidName 
	 * @throws CannotProceed 
	 * @throws NotFound 
	 */
	public DRSServiceClientImpl(String id) throws IOException, NotFound, CannotProceed, InvalidName, org.omg.CORBA.ORBPackage.InvalidName {
		clientID = id;
		//name = objName;
		initORB(null);
		threadPool = Executors.newFixedThreadPool(30);
	}

	/**
	 * Constructor for DRSServiceClientImpl
	 * 
	 * @throws IOException
	 * @throws InvalidName 
	 * @throws CannotProceed 
	 * @throws NotFound 
	 * @throws org.omg.CORBA.ORBPackage.InvalidName 
	 * @see java.lang.Object#Object()
	 */
	public DRSServiceClientImpl(String[] args) throws IOException, NotFound, CannotProceed, InvalidName, org.omg.CORBA.ORBPackage.InvalidName {
		initORB(args);
		threadPool = Executors.newFixedThreadPool(30);
	}

	/**
	 * Initialize ORB.
	 *  
	 * @param args
	 * @throws IOException
	 * @throws InvalidName 
	 * @throws CannotProceed 
	 * @throws NotFound 
	 * @throws org.omg.CORBA.ORBPackage.InvalidName 
	 */
	public void initORB(String[] args) throws IOException, NotFound, CannotProceed, InvalidName, org.omg.CORBA.ORBPackage.InvalidName {

		Properties props = System.getProperties();
		props.setProperty("org.omg.CORBA.ORBClass", "com.sun.corba.se.internal.POA.POAORB");
		props.setProperty("org.omg.CORBA.ORBSingletonClass", "com.sun.corba.se.internal.corba.ORBSingleton");

		// Initialize the ORB
		orb = org.omg.CORBA.ORB.init((String[])args, props);

		// Enable Naming Service with object name
		org.omg.CORBA.Object ncobj = orb.resolve_initial_references("NameService");
		NamingContextExt nc = NamingContextExtHelper.narrow(ncobj);
		org.omg.CORBA.Object obj = nc.resolve_str("DRSObject");

		target = DRStore.DRSServiceHelper.narrow(obj);		
	}

	/**
	 * Obtain ORB Interface.
	 * 
	 * @return
	 */
	public DRStore.DRSService getORBInterface() {
		return target;
	}

	/**
	 * Shutdown ORB.
	 */
	public void shutdown() {
		orb.shutdown(true);
	}

	public void startInvocation(int job, String id, String item, int num, String ex, int exnum) throws RemoteException {
		threadPool.execute(ci = new ClientInvocation(this, job, id, item, num, ex, exnum));
	}

	static void printHello(DRSServiceClientImpl servant){
		StringHolder s = new StringHolder();
		s.value = servant.clientID;
		servant.getORBInterface().hello(s);
		System.out.println(s.value);
	}
	
	
	/**
	 * Test driver for DRSServiceClientImpl.
	 * 
	 * @param args
	 * @throws org.omg.CORBA.ORBPackage.InvalidName 
	 * @throws InvalidName 
	 * @throws CannotProceed 
	 * @throws NotFound 
	 */
	public static void main(String[] args) throws NotFound, CannotProceed, InvalidName, org.omg.CORBA.ORBPackage.InvalidName {
		try {
			// client obj
			DRSServiceClientImpl client = new DRSServiceClientImpl("Client");
			printHello(client);
			
			// the following block should be uncommented for demo 
			
			client.startInvocation(1, "M43456", "1111", 8, "", 0);		// buy
			client.startInvocation(1, "V76456", "2222", 32, "", 0);		// buy, should give different result in rm2  
			client.startInvocation(2, "V11223", "4444", 57, "", 0);		// return
			client.startInvocation(2, "M22345", "3333", 3, "", 0);		// return
			client.startInvocation(3, "T32346", "2222", 0, "", 0);		// check
			client.startInvocation(4, "V21223", "2222", 11, "4444", 12);// exchange
			
			Boolean prompt = true;
			String id, item, id2ex = null;
			int choice, num = 0, num2ex=0;
			do{
				@SuppressWarnings("resource")
				Scanner in = new Scanner(System.in);
				System.out.println("\nPlease choose a task from below: \nBuy: 1\nReturn: 2\nCheck: 3\nExchange: 4\nQuit: 0");
				choice = in.nextInt();
				if (choice == 0){
					System.out.println("Thank you client, for using DRS!");
					prompt = false; 
					break;
				} else if(choice == 1 || choice == 2) {
					System.out.println("Quantity: ");
					num = in.nextInt();
				} else if (choice==4){
					in.nextLine();
					System.out.println("Item id of returning item: ");
					id2ex = in.nextLine();
					System.out.println("Quantity of returning item: ");
					num2ex = in.nextInt();
					in.nextLine();
					System.out.println("Quantity of desired item: ");
					num = in.nextInt();
				} else if (choice!=3) {
					System.out.println("Invalid choice, pl. try again.");
					
				}
				in.nextLine();

				System.out.println("Item ID: ");
				item = in.nextLine();

				System.out.println("Please give a CustomerID starting with M, V, or T: ");
				id = in.nextLine();
				if (id.length() != 6) {
					System.out.println("Invalid id, pl. try again.");
					//break;
				}

			client.startInvocation(choice, id, item, num, id2ex, num2ex);

			}while(prompt);
//			client.shutdown();
		}
		catch(IOException ex) {
			ex.printStackTrace();
		}
	}
}

class ClientInvocation implements Runnable {

	DRSServiceClientImpl client;
	int task=0, quantity=0, exNumber=0;
	String customerID="", itemID="", exID="";

	public ClientInvocation(DRSServiceClientImpl c, int job, String id, String item, int num, String ex, int exnum) {
		client = c;
		task=job;
		customerID=id;
		itemID=item; 
		quantity=num;
		exID=ex;
		exNumber=exnum;
	}

		public void run() {

		switch (task) {
		case 1: {
			System.out.println("\n"+client.getORBInterface().buy(customerID, itemID, quantity));
			break;
		}

		case 2: {
			System.out.println("\n"+client.getORBInterface().returnStock(customerID, itemID, quantity));
			break;
		}

		case 3: {
			System.out.println("\n"+client.getORBInterface().checkStock(itemID));
			break;
		}

		case 4: {
			System.out.println("\n"+client.getORBInterface().exchange(customerID, exID, exNumber, itemID, quantity));
			break;
		}
		default: {
			//System.out.println("Invalid, pl. try again.");
			break;
		}

		}
	}
}
